#include "TaskQueue.hpp"
#include "LockGuard.hpp"

#include <iostream>
#include <pthread.h>
using std::cout;
using std::endl;

namespace tp{


TaskQueue:: TaskQueue(int quesize)
:_que_size(quesize)
,_mutex()
,_notEmpty()
,_notFull()
,_flag(true)
{
    _que.reserve(_que_size);
}
TaskQueue::~TaskQueue(){

}

void TaskQueue::push(ElemType ele){
    LockGuard lockguard(_mutex);
    while(full()){
        _notFull.wait(_mutex);
    }
    _que.push_back(ele);
    _notEmpty.notify_one();
}

ElemType TaskQueue::pop(){
    LockGuard Lockguard(_mutex);
    while(empty() && _flag){
        _notEmpty.wait(_mutex);
    }
    if(_flag){
        ElemType ele = _que.front();
        _que.pop_back();
        _notFull.notify_one();
        return ele;
    }else{
        return 0;
    }
}

bool TaskQueue::empty(){
    return _que.size() == 0;
}

bool TaskQueue::full(){
    return _que.size() == _que_size;
}

void TaskQueue::wakeup(){
    _flag = false;
    _notEmpty.notify_all();
}

}

#if 0
#include "Thread.hpp"
class mythread: public tp::Thread{
public:
    mythread(tp::TaskQueue & taskque)
    :_taskque(taskque){}
private:

    void run() override{
        _taskque.push(3);    
    }
private:
    tp::TaskQueue & _taskque;
};

int main()
{
    tp::TaskQueue taskque(3);
    mythread th1(taskque);
    mythread th2(taskque);
    th1.start();
    th2.start();
    cout << taskque.pop() << endl;
    cout << taskque.pop() << endl;


    return 0;
}
# endif
